/*
 * Copyright (C) 2012 by Hao Hou<ghost89413@gmail.com>
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>*
 */
#include <init.h>
#include <ic.h>
#include <loader.h>
#include <xim.h>
#include <pthread.h>
#include <UI.h>
#include <signal.h>
Display* display;
static XErrorHandler   prev_x_error_handler;
static XIOErrorHandler prev_x_io_error_handler;
Window rootwindow;
Atom atom_protocol;
UserConfigure* config;

int x_error_handler(Display* display, XErrorEvent* event)
{
	char str[256];
	XGetErrorText(display, event->error_code, str, 255);
	VINE_LOG_ERROR("X Error %s",str);
	//TODO: handler the error
	
	//forward the error to previous handler
	if(3 == event->error_code && 
	   event->error_code != BadMatch &&
	   prev_x_error_handler)
	{
		prev_x_error_handler(display, event);
	}
	return 0;
}
int x_io_error_handler(Display* display)
{
	VINE_LOG_ERROR("X IO Error %s", DisplayString(display));
	if(prev_x_io_error_handler)
	{
		prev_x_io_error_handler(display);
	}
	return 0;
}
int InitX()
{
	//Open display
	display = XOpenDisplay((char *) NULL);
	if(NULL == display)
	{
		VINE_LOG_ERROR("Can not open display");
		return -1;
	}
	int screen = XDefaultScreen(display);
	rootwindow = XRootWindow(display, screen);
	//initialize error handler
	//prev_x_io_error_handler = XSetIOErrorHandler(x_io_error_handler);
	//prev_x_error_handler    = XSetErrorHandler  (x_error_handler);	
	//get atoms
	atom_protocol = XInternAtom(display, "WM_PROTOCOLS", False);
	//TODO: get atoms here
	VINE_LOG_DEBUG("atom_protocol = %u", atom_protocol);
	VINE_LOG_TRACE("Xlib Initialized Successfully, continuing");
	return 0;
}

int InitConfig(const char* filename)
{
	//TODO clean up config
	if(NULL == config) return -1;
	if(-1 == ParseConfig(config, filename))
	{
		VINE_LOG_ERROR("Parse config file failed");
		return -1;
	}
	return 0;
}
static pthread_t ui_thread;
int InitUI()
{
	FetchValue(config, String, &default_tray_icon, "./image/vine.png","DefaultTrayIcon");
	if(pthread_create(&ui_thread,NULL,ui_main,NULL)) return -1;
	return 0;
}
void SignalHandler(int sig)
{
	switch(sig)
	{
	case SIGINT:
	case SIGTERM:
	case SIGPIPE:
	case SIGSEGV:
		printf("%d\n",sig);
		Finalization();
		exit(0);
	default:
		break;
	}
}
int InitSignals()
{
	//int i;
	//for(i = SIGHUP; i < SIGUNUSED; i ++)
	//{
		//signal(SIGINT , SignalHandler);
	//}
	return 0;
}
void Finalization()
{
	FinalizeIC();
	FinalizeIMEs();
	FinalizeXIM();
	VINE_LOG_INFO("Vine Server Finalized");
}
